home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / termsorc.lha / Extras / Source / term-source.lha / termPhone.c < prev    next >
C/C++ Source or Header  |  1995-09-26  |  27KB  |  1,181 lines

  1. /*
  2. **    termPhone.c
  3. **
  4. **    Phonebook support routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* RemoveDialEntry(struct PhoneNode *Node):
  13.      *
  14.      *    Remove a phone book entry from the dial list.
  15.      */
  16.  
  17. VOID __regargs
  18. RemoveDialEntry(struct PhoneNode *Node)
  19. {
  20.     LONG Count = Node -> Entry -> Count,i;
  21.  
  22.     for(i = 0 ; i < NumPhoneEntries ; i++)
  23.     {
  24.         if(Phonebook[i] -> Count > Count)
  25.         {
  26.             SPrintf(Phonebook[i] -> Node -> LocalName,"%3ld - %s",Phonebook[i] -> Count--,Phonebook[i] -> Header -> Name);
  27.  
  28.             if(Phonebook[i] -> NodeGroup)
  29.                 strcpy(Phonebook[i] -> NodeGroup -> LocalName,Phonebook[i] -> Node -> LocalName);
  30.         }
  31.     }
  32.  
  33.     Node -> Entry -> Count = -1;
  34.  
  35.     SPrintf(Node -> LocalName,"      %s",Node -> Entry -> Header -> Name);
  36.  
  37.     if(Node -> Entry -> NodeGroup)
  38.         strcpy(Node -> Entry -> NodeGroup -> LocalName,Node -> LocalName);
  39. }
  40.  
  41.     /* RemoveDialNode(struct PhoneNode *Node):
  42.      *
  43.      *    Remove a node from the dialing list.
  44.      */
  45.  
  46. VOID __regargs
  47. RemoveDialNode(struct PhoneNode *Node)
  48. {
  49.     if(Node)
  50.     {
  51.             /* If it's got a name it was built in the phone book panel,
  52.              * else the ARexx interface has linked it into the list.
  53.              */
  54.  
  55.         if(Node -> VanillaNode . ln_Name && Node -> VanillaNode . ln_Name[0])
  56.         {
  57.             LONG Count = Node -> Entry -> Count,i;
  58.  
  59.                 /* Adjust all entries. */
  60.  
  61.             for(i = 0 ; i < NumPhoneEntries ; i++)
  62.             {
  63.                 if(Phonebook[i] -> Count > Count)
  64.                     Phonebook[i] -> Count--;
  65.             }
  66.  
  67.                 /* Can the index count. */
  68.  
  69.             Node -> Entry -> Count = -1;
  70.         }
  71.     }
  72. }
  73.  
  74.     /* SortToList(struct PhoneNode *PhoneNode,struct PhoneEntry *Entry):
  75.      *
  76.      *    Add a node to the dial list.
  77.      */
  78.  
  79. BOOL __regargs
  80. SortToList(struct PhoneNode *PhoneNode,struct PhoneEntry *Entry)
  81. {
  82.     BOOLEAN JustCreated = FALSE;
  83.  
  84.         /* No dial list prepared? Let's create one! */
  85.  
  86.     if(!DialList)
  87.     {
  88.         if(DialList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  89.         {
  90.             NewList(DialList);
  91.  
  92.             JustCreated = TRUE;
  93.         }
  94.     }
  95.  
  96.         /* Do we have a dial list to mangle? */
  97.  
  98.     if(DialList)
  99.     {
  100.         struct PhoneNode *NewNode;
  101.  
  102.             /* Create a new node to be added to the dial list. */
  103.  
  104.         if(NewNode = (struct PhoneNode *)AllocVecPooled(sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
  105.         {
  106.             struct PhoneNode *Node = (struct PhoneNode *)DialList -> lh_Head;
  107.  
  108.                 /* Take care of the name and the corresponding phone book entry. */
  109.  
  110.             NewNode -> VanillaNode . ln_Name = NewNode -> LocalName;
  111.  
  112.             if(Entry)
  113.             {
  114.                 NewNode -> Entry = Entry;
  115.  
  116.                 SPrintf(NewNode -> LocalName,"      %s",Entry -> Header -> Name);
  117.             }
  118.             else
  119.             {
  120.                 NewNode -> Entry = PhoneNode -> Entry;
  121.  
  122.                 strcpy(NewNode -> LocalName,PhoneNode -> LocalName);
  123.             }
  124.  
  125.                 /* Install back-link. */
  126.  
  127.             NewNode -> Entry -> Node = NewNode;
  128.  
  129.                 /* Sort the node into the list. */
  130.  
  131.             while(Node -> VanillaNode . ln_Succ)
  132.             {
  133.                 if(Node -> Entry -> Count > NewNode -> Entry -> Count)
  134.                 {
  135.                     if(Node == (struct PhoneNode *)DialList -> lh_Head)
  136.                         AddHead(DialList,&NewNode -> VanillaNode);
  137.                     else
  138.                         Insert(DialList,&NewNode -> VanillaNode,Node -> VanillaNode . ln_Pred);
  139.  
  140.                     return(TRUE);
  141.                 }
  142.  
  143.                 Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ;
  144.             }
  145.  
  146.             AddTail(DialList,&NewNode -> VanillaNode);
  147.  
  148.             return(TRUE);
  149.         }
  150.     }
  151.  
  152.     if(JustCreated)
  153.     {
  154.         FreeVecPooled(DialList);
  155.         DialList = NULL;
  156.     }
  157.  
  158.     return(FALSE);
  159. }
  160.  
  161.     /* FreeDialList(BYTE ClearAll):
  162.      *
  163.      *    Release the contents of the dial list.
  164.      */
  165.  
  166. VOID __regargs
  167. FreeDialList(BYTE ClearAll)
  168. {
  169.     if(DialList)
  170.     {
  171.         struct PhoneNode *SubNode,*NextNode;
  172.  
  173.         for(SubNode = (struct PhoneNode *)DialList -> lh_Head ; NextNode = (struct PhoneNode *)SubNode -> VanillaNode . ln_Succ ; SubNode = NextNode)
  174.         {
  175.             if(ClearAll || !SubNode -> VanillaNode . ln_Name || !SubNode -> VanillaNode . ln_Name[0])
  176.                 FreeVecPooled(SubNode);
  177.         }
  178.  
  179.         FreeVecPooled(DialList);
  180.  
  181.         DialList = NULL;
  182.     }
  183. }
  184.  
  185.     /* CreatePhoneList():
  186.      *
  187.      *    Turn the array of pointers to phonebook entries into
  188.      *    a linked standard Amiga List (gadtools needs this).
  189.      */
  190.  
  191. struct List *
  192. CreatePhoneList()
  193. {
  194.     struct List *PhoneList;
  195.  
  196.     if(Phonebook && NumPhoneEntries)
  197.     {
  198.         struct PhoneNode *PhoneNode;
  199.  
  200.         if(PhoneList = (struct List *)AllocVecPooled(sizeof(struct List) + NumPhoneEntries * sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
  201.         {
  202.             LONG i;
  203.  
  204.             NewList(PhoneList);
  205.  
  206.             PhoneNode = (struct PhoneNode *)(PhoneList + 1);
  207.  
  208.             for(i = 0 ; i < NumPhoneEntries ; i++)
  209.             {
  210.                 if(Phonebook[i] -> Count != -1)
  211.                 {
  212.                     SPrintf(PhoneNode[i] . LocalName,"%3ld - %s",Phonebook[i] -> Count + 1,Phonebook[i] -> Header -> Name);
  213.  
  214.                     if(Phonebook[i] -> NodeGroup)
  215.                         strcpy(Phonebook[i] -> NodeGroup -> LocalName,PhoneNode[i] . LocalName);
  216.                 }
  217.                 else
  218.                 {
  219.                     SPrintf(PhoneNode[i] . LocalName,"      %s",Phonebook[i] -> Header -> Name);
  220.  
  221.                     if(Phonebook[i] -> NodeGroup)
  222.                         strcpy(Phonebook[i] -> NodeGroup -> LocalName,PhoneNode[i] . LocalName);
  223.                 }
  224.  
  225.                 PhoneNode[i] . VanillaNode . ln_Name = PhoneNode[i] . LocalName;
  226.  
  227.                 Phonebook[i] -> Node = &PhoneNode[i];
  228.  
  229.                 PhoneNode[i] . Entry = Phonebook[i];
  230.  
  231.                 AddTail(PhoneList,&PhoneNode[i]);
  232.             }
  233.  
  234.             return(PhoneList);
  235.         }
  236.     }
  237.     else
  238.     {
  239.         if(PhoneList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  240.         {
  241.             NewList(PhoneList);
  242.  
  243.             return(PhoneList);
  244.         }
  245.     }
  246.  
  247.     return(NULL);
  248. }
  249.  
  250.     /* UpdatePhoneList(struct List *PhoneList):
  251.      *
  252.      *    Rebuilds the phone header list, such as after entries got moved.
  253.      */
  254.  
  255. VOID __regargs
  256. UpdatePhoneList(struct List *PhoneList)
  257. {
  258.     struct PhoneNode    *PhoneNode;
  259.     LONG             i;
  260.  
  261.     for(i = 0, PhoneNode = (struct PhoneNode *)PhoneList -> lh_Head ; i < NumPhoneEntries && PhoneNode -> VanillaNode . ln_Succ ; i++, PhoneNode = (struct PhoneNode *)PhoneNode -> VanillaNode . ln_Succ)
  262.     {
  263.         if(Phonebook[i] -> Count != -1)
  264.         {
  265.             SPrintf(PhoneNode -> LocalName,"%3ld - %s",Phonebook[i] -> Count + 1,Phonebook[i] -> Header -> Name);
  266.  
  267.             if(Phonebook[i] -> NodeGroup)
  268.                 SPrintf(Phonebook[i] -> NodeGroup -> LocalName,"%3ld - %s",Phonebook[i] -> Count + 1,Phonebook[i] -> Header -> Name);
  269.         }
  270.         else
  271.         {
  272.             SPrintf(PhoneNode -> LocalName,"      %s",Phonebook[i] -> Header -> Name);
  273.  
  274.             if(Phonebook[i] -> NodeGroup)
  275.                 SPrintf(Phonebook[i] -> NodeGroup -> LocalName,"      %s",Phonebook[i] -> Header -> Name);
  276.         }
  277.  
  278.         Phonebook[i] -> Node = PhoneNode;
  279.  
  280.         PhoneNode -> Entry = Phonebook[i];
  281.     }
  282. }
  283.  
  284.     /* DeletePhoneList(struct List *PhoneList):
  285.      *
  286.      *    Delete the entries listed in the Amiga List
  287.      *    created by the routine above.
  288.      */
  289.  
  290. VOID __regargs
  291. DeletePhoneList(struct List *PhoneList)
  292. {
  293.     FreeVecPooled(PhoneList);
  294. }
  295.  
  296.     /* Compare(struct PhoneEntry **A,struct PhoneEntry **B):
  297.      *
  298.      *    Comparison subroutine required by the QuickSort
  299.      *    call below.
  300.      */
  301.  
  302. STATIC int __stdargs
  303. Compare(struct PhoneEntry **A,struct PhoneEntry **B)
  304. {
  305.         /* Has entry A been selected? */
  306.  
  307.     if((*A) -> Count == -1)
  308.     {
  309.             /* If entry B isn't selected either, compare the
  310.              * names lexically, else entry B is supposed
  311.              * to be `smaller' than entry A.
  312.              */
  313.  
  314.         if((*B) -> Count == -1)
  315.             return(Strcoll((*A) -> Header -> Name,(*B) -> Header -> Name));
  316.         else
  317.             return(1);
  318.     }
  319.     else
  320.     {
  321.             /* If entry B isn't selected, entry A is supposed
  322.              * to be `smaller' than entry B, else return
  323.              * the difference between both entries.
  324.              */
  325.  
  326.         if((*B) -> Count == -1)
  327.             return(-1);
  328.         else
  329.             return((*A) -> Count - (*B) -> Count);
  330.     }
  331. }
  332.  
  333. STATIC int __stdargs
  334. CompareInverse(struct PhoneEntry **B,struct PhoneEntry **A)
  335. {
  336.     if((*A) -> Count == -1)
  337.     {
  338.         if((*B) -> Count == -1)
  339.             return(Strcoll((*A) -> Header -> Name,(*B) -> Header -> Name));
  340.         else
  341.             return(1);
  342.     }
  343.     else
  344.     {
  345.         if((*B) -> Count == -1)
  346.             return(-1);
  347.         else
  348.             return((*A) -> Count - (*B) -> Count);
  349.     }
  350. }
  351.  
  352. STATIC int __stdargs
  353. CompareName(struct PhoneEntry **A,struct PhoneEntry **B)
  354. {
  355.     return(Strcoll((*A) -> Header -> Name,(*B) -> Header -> Name));
  356. }
  357.  
  358. STATIC int __stdargs
  359. CompareNumber(struct PhoneEntry **A,struct PhoneEntry **B)
  360. {
  361.     return(Strcoll((*A) -> Header -> Number,(*B) -> Header -> Number));
  362. }
  363.  
  364. STATIC int __stdargs
  365. CompareComment(struct PhoneEntry **A,struct PhoneEntry **B)
  366. {
  367.     return(Strcoll((*A) -> Header -> Comment,(*B) -> Header -> Comment));
  368. }
  369.  
  370. STATIC int __stdargs
  371. CompareInverseName(struct PhoneEntry **B,struct PhoneEntry **A)
  372. {
  373.     return(Strcoll((*A) -> Header -> Name,(*B) -> Header -> Name));
  374. }
  375.  
  376. STATIC int __stdargs
  377. CompareInverseNumber(struct PhoneEntry **B,struct PhoneEntry **A)
  378. {
  379.     return(Strcoll((*A) -> Header -> Number,(*B) -> Header -> Number));
  380. }
  381.  
  382. STATIC int __stdargs
  383. CompareInverseComment(struct PhoneEntry **B,struct PhoneEntry **A)
  384. {
  385.     return(Strcoll((*A) -> Header -> Comment,(*B) -> Header -> Comment));
  386. }
  387.  
  388.     /* SortPhoneEntries():
  389.      *
  390.      *    Sorts the current phone list array in ascending order.
  391.      */
  392.  
  393. VOID __regargs
  394. SortPhoneEntries(struct List *List,WORD How,BOOL ReverseOrder)
  395. {
  396.     int (* __stdargs SortFunc)(struct PhoneEntry **B,struct PhoneEntry **A);
  397.  
  398.     switch(How)
  399.     {
  400.         case SORT_NAME:
  401.  
  402.             if(ReverseOrder)
  403.                 SortFunc = CompareInverseName;
  404.             else
  405.                 SortFunc = CompareName;
  406.  
  407.             break;
  408.  
  409.         case SORT_COMMENT:
  410.  
  411.             if(ReverseOrder)
  412.                 SortFunc = CompareInverseComment;
  413.             else
  414.                 SortFunc = CompareComment;
  415.             break;
  416.  
  417.         case SORT_NUMBER:
  418.  
  419.             if(ReverseOrder)
  420.                 SortFunc = CompareInverseNumber;
  421.             else
  422.                 SortFunc = CompareNumber;
  423.             break;
  424.  
  425.         case SORT_SELECTION:
  426.  
  427.             if(ReverseOrder)
  428.                 SortFunc = CompareInverse;
  429.             else
  430.                 SortFunc = Compare;
  431.  
  432.             break;
  433.  
  434.         default:
  435.  
  436.             SortFunc = CompareName;
  437.             break;
  438.     }
  439.  
  440.     if(!List)
  441.         qsort((APTR)Phonebook,NumPhoneEntries,sizeof(struct PhoneEntry *),SortFunc);
  442.     else
  443.     {
  444.         LONG             Count;
  445.         struct PhoneNode    *Node;
  446.  
  447.         for(Count = 0, Node = (struct PhoneNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ)
  448.             Count++;
  449.  
  450.         if(Count)
  451.         {
  452.             struct PhoneEntry **Table;
  453.  
  454.             if(Table = (struct PhoneEntry **)AllocVecPooled(sizeof(struct PhoneEntry *) * Count,MEMF_ANY))
  455.             {
  456.                 for(Count = 0, Node = (struct PhoneNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ)
  457.                     Table[Count++] = Node -> Entry;
  458.  
  459.                 qsort((APTR)Table,Count,sizeof(struct PhoneEntry *),SortFunc);
  460.  
  461.                 for(Count = 0, Node = (struct PhoneNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ)
  462.                 {
  463.                     Node -> Entry = Table[Count++];
  464.  
  465.                     strcpy(Node -> LocalName,Node -> Entry -> Node -> LocalName);
  466.                 }
  467.  
  468.                 FreeVecPooled(Table);
  469.             }
  470.         }
  471.     }
  472. }
  473.  
  474.     /* FreeTimeDateNode(struct TimeDateNode *Node):
  475.      *
  476.      *    Free the memory allocated for a TimeDateNode and
  477.      *    the associated data table.
  478.      */
  479.  
  480. VOID __regargs
  481. FreeTimeDateNode(struct TimeDateNode *Node)
  482. {
  483.     FreeVecPooled(Node -> Table);
  484.  
  485.     FreeVecPooled(Node);
  486. }
  487.  
  488.     /* FreeTimeDateList(struct List *List):
  489.      *
  490.      *    Free a list of TimeDateNodes.
  491.      */
  492.  
  493. VOID __regargs
  494. FreeTimeDateList(struct List *List)
  495. {
  496.     if(List)
  497.     {
  498.         struct Node *Node;
  499.  
  500.         while(Node = RemHead(List))
  501.             FreeTimeDateNode((struct TimeDateNode *)Node);
  502.     }
  503. }
  504.  
  505.     /* CopyTimeDateList(struct List *From,struct List *To,BYTE SkipFirst):
  506.      *
  507.      *    Copies the TimeDateNode list from one location into
  508.      *    another.
  509.      */
  510.  
  511. VOID __regargs
  512. CopyTimeDateList(struct List *From,struct List *To,BYTE SkipFirst)
  513. {
  514.     struct TimeDateNode *FromNode,*ToNode;
  515.  
  516.     FromNode = (struct TimeDateNode *)From -> lh_Head;
  517.  
  518.     if(SkipFirst)
  519.         FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  520.  
  521.     while(FromNode -> VanillaNode . ln_Succ)
  522.     {
  523.         if(ToNode = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY))
  524.         {
  525.             CopyMem(FromNode,ToNode,sizeof(struct TimeDateNode));
  526.  
  527.             ToNode -> VanillaNode . ln_Name = ToNode -> Buffer;
  528.  
  529.             if(ToNode -> Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * FromNode -> Table[0] . Count,MEMF_ANY))
  530.             {
  531.                 CopyMem(FromNode -> Table,ToNode -> Table,sizeof(struct TimeDate) * FromNode -> Table[0] . Count);
  532.  
  533.                 AddTail(To,&ToNode -> VanillaNode);
  534.             }
  535.             else
  536.                 FreeVecPooled(ToNode);
  537.         }
  538.  
  539.         FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  540.     }
  541. }
  542.  
  543.     /* AdaptTimeDateNode(struct TimeDateNode *Node):
  544.      *
  545.      *    Adapt the title and comment of a TimeDateNode.
  546.      */
  547.  
  548. VOID __regargs
  549. AdaptTimeDateNode(struct TimeDateNode *Node)
  550. {
  551.     STRPTR Comment = Node -> Header . Comment[0] ? Node -> Header . Comment : LocaleString(MSG_TERMPHONE_NO_COMMENT_TXT);
  552.  
  553.     if(Node -> Header . Month == -1)
  554.     {
  555.         if(Node -> Header . Day == -1)
  556.             strcpy(Node -> Buffer,LocaleString(MSG_TERMPHONE_STANDARD_SETTINGS_TXT));
  557.         else
  558.             SPrintf(Node -> Buffer,LocaleString(MSG_TERMPHONE_DAYS_TXT),Comment);
  559.     }
  560.     else
  561.         SPrintf(Node -> Buffer,"%2ld %s » %s",Node -> Header . Day,LocaleString(MSG_TERMPHONE_JAN_TXT + Node -> Header . Month),Comment);
  562. }
  563.  
  564.     /* TimeCompare(struct TimeDate *A,struct TimeDate *B):
  565.      *
  566.      *    Comparison routine required by SortTimeTable().
  567.      */
  568.  
  569. STATIC int __stdargs
  570. TimeCompare(struct TimeDate *A,struct TimeDate *B)
  571. {
  572.     return(((LONG)A -> Time) - ((LONG)B -> Time));
  573. }
  574.  
  575.     /* SortTimeTable(struct TimeDateNode *Node):
  576.      *
  577.      *    Sort the time table associated with a
  578.      *    TimeDateNode in ascending order.
  579.      */
  580.  
  581. VOID __regargs
  582. SortTimeTable(struct TimeDateNode *Node)
  583. {
  584.     qsort((APTR)Node -> Table,Node -> Table[0] . Count,sizeof(struct TimeDate),TimeCompare);
  585. }
  586.  
  587.     /* BuildTimeList(struct TimeDateNode *Node):
  588.      *
  589.      *    Build a read-to-display time table list from a TimeDateNode.
  590.      */
  591.  
  592. struct List * __regargs
  593. BuildTimeList(struct TimeDateNode *Node)
  594. {
  595.     struct List *List;
  596.  
  597.     if(List = (struct List *)AllocVecPooled(sizeof(struct List) + Node -> Table[0] . Count * sizeof(struct TimeNode),MEMF_ANY | MEMF_CLEAR))
  598.     {
  599.         struct TimeNode    *Time = (struct TimeNode *)(List + 1);
  600.         UBYTE         LocalBuffer[40];
  601.         LONG         i;
  602.  
  603.         NewList(List);
  604.  
  605.         for(i = 0 ; i < Node -> Table[0] . Count ; i++)
  606.         {
  607.             Time[i] . VanillaNode . ln_Name    = Time[i] . Name;
  608.             Time[i] . Time            = Node -> Table[i] . Time;
  609.  
  610.             FormatTime(LocalBuffer,Time[i] . Time / 6,(Time[i] . Time % 6) * 10,-1);
  611.  
  612.             LocalBuffer[19] = 0;
  613.  
  614.             strcpy(Time[i] . Name,LocalBuffer);
  615.  
  616.             AddTail(List,&Time[i]);
  617.         }
  618.     }
  619.  
  620.     return(List);
  621. }
  622.  
  623.     /* ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time):
  624.      *
  625.      *    Resize the time table associated with a TimeDateNode.
  626.      */
  627.  
  628. BYTE __regargs
  629. ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time)
  630. {
  631.     if(Count != Node -> Table[0] . Count)
  632.     {
  633.         struct TimeDate *Table;
  634.  
  635.         if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  636.         {
  637.             LONG i;
  638.  
  639.             CopyMem(Node -> Table,Table,sizeof(struct TimeDate) * Count);
  640.  
  641.             if(Count > Node -> Table[0] . Count)
  642.             {
  643.                 for(i = Node -> Table[0] . Count ; i < Count ; i++)
  644.                 {
  645.                     CopyMem(&Node -> Table[0],&Table[i],sizeof(struct TimeDate));
  646.  
  647.                     Table[i] . Time = Time;
  648.                 }
  649.             }
  650.  
  651.             for(i = 0 ; i < Count ; i++)
  652.                 Table[i] . Count = Count;
  653.  
  654.             FreeVecPooled(Node -> Table);
  655.  
  656.             Node -> Table = Table;
  657.  
  658.             return(TRUE);
  659.         }
  660.         else
  661.             return(FALSE);
  662.     }
  663.     else
  664.         return(TRUE);
  665. }
  666.  
  667.     /* DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index):
  668.      *
  669.      *    Delete a single timetable entry from a TimeDateNode.
  670.      */
  671.  
  672. BYTE __regargs
  673. DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index)
  674. {
  675.     struct TimeDate    *Table;
  676.     LONG         Count = Node -> Table[0] . Count - 1;
  677.  
  678.     if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  679.     {
  680.         LONG i,j;
  681.  
  682.         for(i = j = 0 ; i < Node -> Table[0] . Count ; i++)
  683.         {
  684.             if(i != Index)
  685.             {
  686.                 CopyMem(&Node -> Table[i],&Table[j],sizeof(struct TimeDate));
  687.  
  688.                 Table[j++] . Count = Count;
  689.             }
  690.         }
  691.  
  692.         FreeVecPooled(Node -> Table);
  693.  
  694.         Node -> Table = Table;
  695.  
  696.         return(TRUE);
  697.     }
  698.     else
  699.         return(FALSE);
  700. }
  701.  
  702.     /* CreateTimeDateNode(BYTE Month,BYTE Day,STRPTR Comment,LONG Count):
  703.      *
  704.      *    Create a new TimeDateNode including time table entries.
  705.      */
  706.  
  707. struct TimeDateNode * __regargs
  708. CreateTimeDateNode(BYTE Month,BYTE Day,STRPTR Comment,LONG Count)
  709. {
  710.     struct TimeDateNode *Node;
  711.  
  712.     if(Node = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY | MEMF_CLEAR))
  713.     {
  714.         if(Node -> Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  715.         {
  716.             Node -> VanillaNode . ln_Name            = Node -> Buffer;
  717.  
  718.             Node -> Header . Month                = Month;
  719.             Node -> Header . Day                = Day;
  720. /*
  721.             Node -> Table[0] . PayPerUnit[DT_FIRST_UNIT]    = 23;
  722.             Node -> Table[0] . SecPerUnit[DT_FIRST_UNIT]    =  6 * 60;
  723.             Node -> Table[0] . PayPerUnit[DT_NEXT_UNIT]    = 23;
  724.             Node -> Table[0] . SecPerUnit[DT_NEXT_UNIT]    =  6 * 60;
  725. */
  726.             Node -> Table[0] . PayPerUnit[DT_FIRST_UNIT]    = 0;
  727.             Node -> Table[0] . SecPerUnit[DT_FIRST_UNIT]    = 0;
  728.             Node -> Table[0] . PayPerUnit[DT_NEXT_UNIT]    = 0;
  729.             Node -> Table[0] . SecPerUnit[DT_NEXT_UNIT]    = 0;
  730.             Node -> Table[0] . Time                = DT_GET_TIME( 8,0);
  731.             Node -> Table[0] . Count            = Count;
  732.  
  733.             if(Count > 1)
  734.             {
  735. /*
  736.                 Node -> Table[1] . PayPerUnit[DT_FIRST_UNIT]    = 23;
  737.                 Node -> Table[1] . SecPerUnit[DT_FIRST_UNIT]    = 12 * 60;
  738.                 Node -> Table[1] . PayPerUnit[DT_NEXT_UNIT]    = 23;
  739.                 Node -> Table[1] . SecPerUnit[DT_NEXT_UNIT]    = 12 * 60;
  740. */
  741.                 Node -> Table[1] . PayPerUnit[DT_FIRST_UNIT]    = 0;
  742.                 Node -> Table[1] . SecPerUnit[DT_FIRST_UNIT]    = 0;
  743.                 Node -> Table[1] . PayPerUnit[DT_NEXT_UNIT]    = 0;
  744.                 Node -> Table[1] . SecPerUnit[DT_NEXT_UNIT]    = 0;
  745.                 Node -> Table[1] . Time                = DT_GET_TIME(18,0);
  746.                 Node -> Table[1] . Count            = Count;
  747.             }
  748.  
  749.             strcpy(Node -> Header . Comment,Comment);
  750.  
  751.             AdaptTimeDateNode(Node);
  752.  
  753.             return(Node);
  754.         }
  755.         else
  756.             FreeVecPooled(Node);
  757.     }
  758.  
  759.     return(NULL);
  760. }
  761.  
  762.     /* RemPhoneEntry(struct PhoneNode *Node,LONG Num):
  763.      *
  764.      *    Remove a given entry from the phone book.
  765.      */
  766.  
  767. VOID __regargs
  768. RemPhoneEntry(struct PhoneNode *Node,LONG Num)
  769. {
  770.     struct PhoneEntry    *Entry;
  771.     LONG             i;
  772.  
  773.     if(Node)
  774.     {
  775.         for(i = 0 ; i < NumPhoneEntries ; i++)
  776.         {
  777.             if(Phonebook[i] -> Node == Node || Phonebook[i] -> NodeGroup == Node)
  778.             {
  779.                 Num = i;
  780.                 break;
  781.             }
  782.         }
  783.     }
  784.  
  785.     Entry = Phonebook[Num];
  786.  
  787.     for(i = Num ; i < NumPhoneEntries ; i++)
  788.         Phonebook[i] = Phonebook[i + 1];
  789.  
  790.     Phonebook[NumPhoneEntries--] = NULL;
  791.  
  792.     if(Entry -> Config)
  793.         DeleteConfiguration(Entry -> Config);
  794.  
  795.     FreeTimeDateList((struct List *)&Entry -> TimeDateList);
  796.  
  797.         // Is this entry member of a group?
  798.  
  799.     if(Entry -> NodeGroup)
  800.     {
  801.             // Disconnect it
  802.  
  803.         Remove((struct Node *)Entry -> NodeGroup);
  804.  
  805.         FreeVecPooled(Entry -> NodeGroup);
  806.     }
  807.  
  808.     FreeVecPooled(Entry);
  809. }
  810.  
  811.     /* NewPhoneEntry():
  812.      *
  813.      *    Create a new phone book entry with default values and
  814.      *    add it to the array. Expand the phone book if necessary.
  815.      */
  816.  
  817. BYTE
  818. NewPhoneEntry()
  819. {
  820.     struct PhoneEntry    **PrivatePhonebook;
  821.     LONG             PrivatePhoneSize,i;
  822.  
  823.         /* The phone book is filled `to the brim', so let's expand
  824.          * it.
  825.          */
  826.  
  827.     if(NumPhoneEntries + 1 > PhoneSize)
  828.     {
  829.             /* Allocate another phone book. */
  830.  
  831.         if(PrivatePhonebook = CreatePhonebook(PhoneSize + 1,&PrivatePhoneSize,FALSE))
  832.         {
  833.                 /* Copy the data. */
  834.  
  835.             if(Phonebook && PhoneSize)
  836.             {
  837.                 for(i = 0 ; i < PhoneSize ; i++)
  838.                     PrivatePhonebook[i] = Phonebook[i];
  839.  
  840.                     /* Remove the old phonebook. */
  841.  
  842.                 DeletePhonebook(Phonebook,PhoneSize,FALSE);
  843.             }
  844.  
  845.                 /* Assign the new pointers. */
  846.  
  847.             Phonebook = PrivatePhonebook;
  848.             PhoneSize = PrivatePhoneSize;
  849.         }
  850.         else
  851.             return(FALSE);
  852.     }
  853.  
  854.         /* Allocate another entry and add it to the phone book. */
  855.  
  856.     if(Phonebook[NumPhoneEntries] = (struct PhoneEntry *)AllocVecPooled(sizeof(struct PhoneEntry) + sizeof(struct PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  857.     {
  858.         if(Phonebook[NumPhoneEntries] -> Config = CreateConfiguration(FALSE))
  859.         {
  860.             struct TimeDateNode *TimeDateNode;
  861.  
  862.             Phonebook[NumPhoneEntries] -> Header = (struct PhoneHeader *)(Phonebook[NumPhoneEntries] + 1);
  863.  
  864.             strcpy(Phonebook[NumPhoneEntries] -> Header -> Name,LocaleString(MSG_TERMPHONE_UNUSED_ENTRY_TXT));
  865.  
  866.             Phonebook[NumPhoneEntries] -> Count = -1;
  867.  
  868.             Phonebook[NumPhoneEntries] -> Header -> ID = PhonebookID++;
  869.  
  870.             GetSysTime(&Phonebook[NumPhoneEntries] -> Header -> Creation);
  871.  
  872.             NewList((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList);
  873.  
  874.             if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
  875.                 AddTail((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList,&TimeDateNode -> VanillaNode);
  876.  
  877.             NumPhoneEntries++;
  878.  
  879.             return(TRUE);
  880.         }
  881.  
  882.         FreeVecPooled(Phonebook[NumPhoneEntries]);
  883.  
  884.         Phonebook[NumPhoneEntries] = NULL;
  885.     }
  886.  
  887.     return(FALSE);
  888. }
  889.  
  890.     /* MergePhonebook(PhonebookHandle *BookHandle):
  891.      *
  892.      *    Merges the current phonebook with new data.
  893.      */
  894.  
  895. struct PhoneEntry ** __regargs
  896. MergePhonebook(PhonebookHandle *BookHandle)
  897. {
  898.     struct PhoneEntry    **PrivatePhonebook;
  899.     LONG             PrivatePhoneSize = 0;
  900.  
  901.     if(PrivatePhonebook = CreatePhonebook(NumPhoneEntries + BookHandle -> NumPhoneEntries,&PrivatePhoneSize,FALSE))
  902.     {
  903.         LONG i,Count = 0;
  904.  
  905.         for(i = 0 ; i < NumPhoneEntries ; i++)
  906.             PrivatePhonebook[Count++] = Phonebook[i];
  907.  
  908.         for(i = 0 ; i < BookHandle -> NumPhoneEntries ; i++)
  909.         {
  910.             PrivatePhonebook[Count] = BookHandle -> Phonebook[i];
  911.  
  912.             PrivatePhonebook[Count] -> Header -> ID = PhonebookID++;
  913.  
  914.             Count++;
  915.         }
  916.  
  917.         DeletePhonebook(Phonebook,PhoneSize,FALSE);
  918.  
  919.         Phonebook    = PrivatePhonebook;
  920.         PhoneSize    = PrivatePhoneSize;
  921.         NumPhoneEntries    = Count;
  922.     }
  923.  
  924.     return(PrivatePhonebook);
  925. }
  926.  
  927.     /* CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries):
  928.      *
  929.      *    Create a new phone entry array (so-called phone book).
  930.      */
  931.  
  932. struct PhoneEntry ** __regargs
  933. CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries)
  934. {
  935.     struct PhoneEntry **PhoneEntry = NULL;
  936.  
  937.     if(Size)
  938.     {
  939.             /* Round the number of phone entries to a
  940.              * multiple of eight.
  941.              */
  942.  
  943.         *AllocSize = (Size + 7) & ~7;
  944.  
  945.             /* Create the list of pointers. */
  946.  
  947.         if(PhoneEntry = (struct PhoneEntry **)AllocVecPooled(*AllocSize * sizeof(struct PhoneEntry *),MEMF_ANY | MEMF_CLEAR))
  948.         {
  949.                 /* And create some entries if necessary. */
  950.  
  951.             if(CreateEntries)
  952.             {
  953.                 BYTE Success = TRUE;
  954.                 LONG i;
  955.  
  956.                 for(i = 0 ; Success && i < Size ; i++)
  957.                 {
  958.                     if(PhoneEntry[i] = (struct PhoneEntry *)AllocVecPooled(sizeof(struct PhoneEntry) + sizeof(struct PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  959.                     {
  960.                         if(PhoneEntry[i] -> Config = CreateConfiguration(FALSE))
  961.                         {
  962.                             PhoneEntry[i] -> Header = (struct PhoneHeader *)(PhoneEntry[i] + 1);
  963.  
  964.                             GetSysTime(&PhoneEntry[i] -> Header -> Creation);
  965.  
  966.                             NewList((struct List *)&PhoneEntry[i] -> TimeDateList);
  967.                         }
  968.                         else
  969.                             Success = FALSE;
  970.                     }
  971.                     else
  972.                         Success = FALSE;
  973.                 }
  974.  
  975.                 if(!Success)
  976.                 {
  977.                     for(i = 0 ; i < *AllocSize ; i++)
  978.                     {
  979.                         if(PhoneEntry[i])
  980.                         {
  981.                             if(PhoneEntry[i] -> Config)
  982.                                 DeleteConfiguration(PhoneEntry[i] -> Config);
  983.  
  984.                             FreeVecPooled(PhoneEntry[i]);
  985.                         }
  986.                     }
  987.  
  988.                     FreeVecPooled(PhoneEntry);
  989.  
  990.                     return(NULL);
  991.                 }
  992.             }
  993.         }
  994.     }
  995.  
  996.     return(PhoneEntry);
  997. }
  998.  
  999.     /* DeletePhonebook(struct PhoneEntry **PhoneBook,LONG Size,BYTE FreeEntries):
  1000.      *
  1001.      *    Deallocates a given phone book and its entries if necessary.
  1002.      */
  1003.  
  1004. VOID __regargs
  1005. DeletePhonebook(struct PhoneEntry **Phonebook,LONG Size,BYTE FreeEntries)
  1006. {
  1007.     if(Phonebook)
  1008.     {
  1009.         if(FreeEntries)
  1010.         {
  1011.             LONG i;
  1012.  
  1013.             for(i = 0 ; i < Size ; i++)
  1014.             {
  1015.                 if(Phonebook[i])
  1016.                 {
  1017.                     FreeTimeDateList((struct List *)&Phonebook[i] -> TimeDateList);
  1018.  
  1019.                     if(Phonebook[i] -> Config)
  1020.                         DeleteConfiguration(Phonebook[i] -> Config);
  1021.  
  1022.                     if(Phonebook[i] -> NodeGroup)
  1023.                     {
  1024.                         Remove((struct Node *)Phonebook[i] -> NodeGroup);
  1025.                         FreeVecPooled(Phonebook[i] -> NodeGroup);
  1026.  
  1027.                         if(!Phonebook[i] -> ThisGroup -> GroupList . mlh_Head -> mln_Succ)
  1028.                         {
  1029.                             Remove((struct Node *)Phonebook[i] -> ThisGroup);
  1030.                             FreeVecPooled(Phonebook[i] -> ThisGroup);
  1031.                         }
  1032.                     }
  1033.  
  1034.                     FreeVecPooled(Phonebook[i]);
  1035.                 }
  1036.             }
  1037.         }
  1038.  
  1039.         FreeVecPooled(Phonebook);
  1040.     }
  1041. }
  1042.  
  1043.     /* DeletePhoneGroupNode(PhoneGroupNode *GroupNode):
  1044.      *
  1045.      *    Delete all PhoneNodes stored in a phone group node list.
  1046.      */
  1047.  
  1048. VOID __regargs
  1049. DeletePhoneGroupNode(PhoneGroupNode *GroupNode)
  1050. {
  1051.     struct PhoneNode *Node;
  1052.  
  1053.     while(Node = (struct PhoneNode *)RemHead((struct List *)&GroupNode -> GroupList))
  1054.     {
  1055.         Node -> Entry -> ThisGroup = NULL;
  1056.         Node -> Entry -> NodeGroup = NULL;
  1057.  
  1058.         FreeVecPooled(Node);
  1059.     }
  1060.  
  1061.     FreeVecPooled(GroupNode);
  1062. }
  1063.  
  1064.     /* DeletePhoneGroupList(struct MinList *List):
  1065.      *
  1066.      *    Delete a phone group node and its associated data.
  1067.      */
  1068.  
  1069. VOID __regargs
  1070. DeletePhoneGroupList(struct MinList *List)
  1071. {
  1072.     PhoneGroupNode *Node;
  1073.  
  1074.     while(Node = (PhoneGroupNode *)RemHead((struct List *)List))
  1075.         DeletePhoneGroupNode(Node);
  1076. }
  1077.  
  1078.     /* InsertSorted(struct List *List,struct Node *Node):
  1079.      *
  1080.      *    Insert a node into a linked list whilst keeping the
  1081.      *    list sorted in alphabetic order.
  1082.      */
  1083.  
  1084. STATIC VOID __regargs
  1085. InsertSorted(struct List *List,struct Node *Node)
  1086. {
  1087.     struct Node    *Other;
  1088.     STRPTR         Name;
  1089.  
  1090.     Name = Node -> ln_Name;
  1091.  
  1092.     for(Other = List -> lh_Head ; Other -> ln_Succ ; Other = Other -> ln_Succ)
  1093.     {
  1094.         if(Strcoll(Name,Other -> ln_Name) <= 0)
  1095.         {
  1096.             if(Other == List -> lh_Head)
  1097.                 AddHead(List,Node);
  1098.             else
  1099.                 Insert(List,Node,Other -> ln_Pred);
  1100.  
  1101.             return;
  1102.         }
  1103.     }
  1104.  
  1105.     AddTail(List,Node);
  1106. }
  1107.  
  1108.     /* CreatePhoneGroup(STRPTR Name,struct MinList *List):
  1109.      *
  1110.      *    Create a phone group with given name, unless the named group
  1111.      *    already exists, in which case the existing group will be returned.
  1112.      */
  1113.  
  1114. PhoneGroupNode * __regargs
  1115. CreatePhoneGroup(STRPTR Name,struct MinList *List)
  1116. {
  1117.     PhoneGroupNode *Node;
  1118.  
  1119.     for(Node = (PhoneGroupNode *)List -> mlh_Head ; Node -> Node . ln_Succ ; Node = (PhoneGroupNode *)Node -> Node . ln_Succ)
  1120.     {
  1121.         if(!Stricmp(Node -> Node . ln_Name,Name))
  1122.             return(Node);
  1123.     }
  1124.  
  1125.     if(Node = (PhoneGroupNode *)AllocVecPooled(sizeof(PhoneGroupNode),MEMF_ANY|MEMF_CLEAR))
  1126.     {
  1127.         Node -> Node . ln_Name = Node -> LocalName;
  1128.  
  1129.         strcpy(Node -> LocalName,Name);
  1130.  
  1131.         NewList((struct List *)&Node -> GroupList);
  1132.  
  1133.         InsertSorted((struct List *)List,(struct Node *)Node);
  1134.     }
  1135.  
  1136.     return(Node);
  1137. }
  1138.  
  1139.     /* AddGroupEntry(PhoneGroupNode *NewGroup,struct PhoneNode *Node):
  1140.      *
  1141.      *    Add an entry to a phone group. If the entry is already a member of
  1142.      *    a different group, remove it from the other group and add it to the
  1143.      *    given group. Do nothing if the entry is already a member of the
  1144.      *    given group.
  1145.      */
  1146.  
  1147. struct PhoneNode * __regargs
  1148. AddGroupEntry(PhoneGroupNode *NewGroup,struct PhoneNode *Node)
  1149. {
  1150.     if(Node -> Entry -> ThisGroup)
  1151.     {
  1152.         if(Node -> Entry -> ThisGroup == NewGroup)
  1153.             return(Node -> Entry -> NodeGroup);
  1154.         else
  1155.             Remove((struct Node *)Node -> Entry -> NodeGroup);
  1156.     }
  1157.     else
  1158.     {
  1159.         struct PhoneNode *Other;
  1160.  
  1161.         if(Other = (struct PhoneNode *)AllocVecPooled(sizeof(struct PhoneNode),MEMF_ANY|MEMF_CLEAR))
  1162.         {
  1163.             Other -> VanillaNode . ln_Name = Other -> LocalName;
  1164.  
  1165.             Other -> Entry = Node -> Entry;
  1166.  
  1167.             strcpy(Other -> LocalName,Node -> LocalName);
  1168.  
  1169.             Node -> Entry -> NodeGroup = Other;
  1170.         }
  1171.         else
  1172.             return(NULL);
  1173.     }
  1174.  
  1175.     InsertSorted((struct List *)&NewGroup -> GroupList,(struct Node *)Node -> Entry -> NodeGroup);
  1176.  
  1177.     Node -> Entry -> ThisGroup = NewGroup;
  1178.  
  1179.     return(Node -> Entry -> NodeGroup);
  1180. }
  1181.